package es.ubu.ceudaaj.exercise.ud02.t04.l03;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import es.ubu.ceudaaj.exercise.ud02.t04.l03.model.Contactos;
import es.ubu.ceudaaj.exercise.ud02.t04.l03.model.Dataroot;

/**
 * Class representing a list of contacts that can be read and written into and
 * from an xml file.
 * 
 * This version uses JAXB to process the xml.
 * 
 */
public class AgendaJAXB implements Agenda {

	private static final String XML_INPUT_PATH = "src/main/resources/xml/Contactos.xml";
	private static final String XML_OUTPUT_PATH = "src/main/resources/xml/Contactos_new.xml";

	// Path to the JAXB classes (that have been generated first, by using 'jxc')
	private static final String JAXB_PACKAGE = "es.ubu.ceudaaj.exercise.ud02.t04.l03.model";

	// Attribute to keep a reference to the current XML in memory.
	private Dataroot dataroot = null;

	private static AgendaJAXB instance = null;

	/**
	 * Private constructor This class should only be used as singleton
	 */
	private AgendaJAXB() {
	}

	/**
	 * Returns a JAXB based agenda
	 * 
	 * @return AgendaJAXB
	 */
	public static AgendaJAXB getInstance() {
		if (instance == null)
			instance = new AgendaJAXB();
		return instance;
	}

	/**
	 * Main method responsible for printing the console menu and managing the
	 * user selections.
	 * 
	 * @param args
	 * @throws IOException
	 */
	// public static void main( String[] args ) throws IOException {
	// int selectedOption = 0;
	// int selectedContactId = 0;
	// String search = null;
	// System.out.println("hello");
	//
	// // An instance of this class that will represent the current list of
	// contacts.
	// AgendaJAXB agenda = new AgendaJAXB();
	//
	// // Menu loop.
	// while (true) {
	// selectedContactId = 0;
	//
	// Menu.printMenuHeader();
	//
	// agenda.listContacts();
	//
	// Menu.printMainMenu();
	//
	// selectedOption = Menu.readOptionFromConsole();
	//
	// switch (selectedOption) {
	// case 1:
	// agenda.loadXML();
	// Menu.pause();
	// break;
	// case 2:
	// agenda.saveXML();
	// Menu.pause();
	// break;
	// case 3:
	// agenda.createNewContact();
	// break;
	// case 4:
	// selectedContactId = 0;
	// System.out.print("Seleccione el nº de Contacto: ");
	// if ((selectedContactId = Menu.readOptionFromConsole()) > 0) {
	// agenda.printContactDetail(selectedContactId);
	// } else {
	// System.out.println("No es un valor valido");
	// }
	// Menu.pause();
	// break;
	// case 5:
	// selectedContactId = 0;
	// System.out.print("Seleccione el nº de Contacto:");
	// if ((selectedContactId = Menu.readOptionFromConsole()) > 0) {
	// agenda.editContact(selectedContactId);
	// } else {
	// System.out.println("No es un valor valido");
	// }
	// Menu.pause();
	// break;
	// case 6:
	// selectedContactId = 0;
	// System.out.print("Seleccione el nº de Contacto: ");
	// if ((selectedContactId = Menu.readOptionFromConsole()) > 0) {
	// agenda.deleteContact(selectedContactId);
	// } else {
	// System.out.println("No es un valor valido");
	// }
	// Menu.pause();
	// break;
	// case 7:
	// System.out.print("Nombre del contacto buscado: ");
	// search = Menu.readStringFromConsole();
	// if ( search != null && !search.isEmpty()) {
	// agenda.searchByName(search);
	// } else {
	// System.out.println("No es un valor valido");
	// }
	// Menu.pause();
	// break;
	// case 8:
	// System.out.print("Cargo del contacto buscado: ");
	// search = Menu.readStringFromConsole();
	// if ( search != null && !search.isEmpty()) {
	// agenda.searchByJob(search);
	// } else {
	// System.out.println("No es un valor valido");
	// }
	// Menu.pause();
	// break;
	// case 9:
	// System.out.print("C. Postal del contacto buscado: ");
	// search = Menu.readStringFromConsole();
	// if ( search != null && !search.isEmpty()) {
	// agenda.searchByPostalCode(search);
	// } else {
	// System.out.println("No es un valor valido");
	// }
	// Menu.pause();
	// break;
	// default:
	// System.out.println("No es una opcion valida.");
	// Menu.pause();
	// break;
	// }
	// }
	// }

	/**
	 * Shows a list of current contacts on console. (Only name and surnames).
	 */
	/*
	 * public void listContacts() { int index = 0; if (dataroot != null &&
	 * !dataroot.getContactos().isEmpty()) { for (Contactos contact :
	 * dataroot.getContactos()) { index ++; System.out.println(index + ". " +
	 * contact.getApellidos() + ", " + contact.getNombre()); } } else {
	 * System.out.println("(lista vacia)"); } }
	 */

	/**
	 * Prints detailed information of selected user on console.
	 * 
	 * @param index
	 *            Position of selected contact.
	 * @throws IOException
	 */
	/*
	 * public void printContactDetail(int index){ StringBuilder sb; if (dataroot
	 * != null && dataroot.getContactos() != null &&
	 * dataroot.getContactos().size() >= index && index > 0) { Contactos cont =
	 * dataroot.getContactos().get(index - 1); sb = new
	 * StringBuilder("Detalle del contacto " + index + ": ");
	 * sb.append("\n\tID: ").append(cont.getIdContacto());
	 * sb.append("\n\tNombre: "); if (cont.getEstimado() != null) {
	 * sb.append(cont.getEstimado()).append(" "); } if (cont.getNombre() !=
	 * null) { sb.append(cont.getNombre()).append(" "); } if
	 * (cont.getApellidos() != null) { sb.append(cont.getApellidos()); } if
	 * (cont.getDireccion() != null) { sb.append("\n\tDireccion: ");
	 * sb.append(cont.getDireccion()); } if (cont.getCodPostal() != null) {
	 * sb.append(", ").append(cont.getCodPostal()); } if (cont.getCiudad() !=
	 * null) { sb.append(", ").append(cont.getCiudad()); } if (cont.getPais() !=
	 * null) { sb.append(", ").append(cont.getPais()); } if (cont.getCargo() !=
	 * null) { sb.append("\n\tCargo: ").append(cont.getCargo()); } if
	 * (cont.getTelefonoTrabajo() != null) {
	 * sb.append("\n\tTfno. trabajo: ").append(cont.getTelefonoTrabajo()); } if
	 * (cont.getExtensionTrabajo() != null) {
	 * sb.append("\n\tExt. trabajo: ").append(cont.getExtensionTrabajo()); } if
	 * (cont.getNumFax() != null) {
	 * sb.append("\n\tFax: ").append(cont.getNumFax()); } if
	 * (cont.getNomCorreoElectronico() != null) {
	 * sb.append("\n\tEmail: ").append(cont.getNomCorreoElectronico()); } //
	 * System.out.println("Tipo contacto: "); //TODO
	 * //System.out.println("Llamadas: ");//TODO System.out.println(sb); } else
	 * { System.out.println("No existe en la lista de contactos."); } }
	 */

	/**
	 * Creates a new contact and adds it to the XML representation in memory.
	 * 
	 * @throws IOException
	 */
	public void createNewContact(Contactos nuevocontacto) {
		/*
		 * InputStreamReader isr = new InputStreamReader(System.in);
		 * BufferedReader br = new BufferedReader(isr);
		 * System.out.print("Introduzca Nombre: "); String name = br.readLine();
		 * System.out.print("Introduzca Apellidos: "); String surnames =
		 * br.readLine(); System.out.print("Introduzca Telefono: "); String
		 * phone = br.readLine(); System.out.print("Introduzca eMail: "); String
		 * mail = br.readLine();
		 */

		if (dataroot == null) {
			dataroot = new Dataroot();
			GregorianCalendar c = new GregorianCalendar();
			c.setTime(new Date());
			XMLGregorianCalendar xmlgc;
			try {
				xmlgc = DatatypeFactory.newInstance()
						.newXMLGregorianCalendar(c);
				dataroot.setGenerated(xmlgc);
			} catch (DatatypeConfigurationException e) {
				System.err.println("Error al crear nuevo contacto: " + e);
				return;
			}
		}

		Contactos cont = new Contactos();
		cont.setIdContacto(dataroot.getContactos().size() + 1);
		cont.setNombre(nuevocontacto.getNombre());
		cont.setApellidos(nuevocontacto.getApellidos());
		cont.setTelefonoTrabajo(nuevocontacto.getTelefonoMovil());
		cont.setNomCorreoElectronico(nuevocontacto.getNomCorreoElectronico());

		dataroot.getContactos().add(cont);
	}

	/**
	 * Method for seeing the information for the selected contact in the XML
	 * representation in memory.
	 * 
	 * @param index
	 *            Position of selected contact.
	 * @throws IOException
	 */
	public Contactos seeContact(int index) {
		Contactos nuevoContacto = null;
		if (dataroot != null && dataroot.getContactos() != null
				&& dataroot.getContactos().size() >= index && index > 0) {

			nuevoContacto = dataroot.getContactos().get(index - 1);

			/*
			 * nuevoContacto.getNombre(); nuevoContacto.getApellidos();
			 * nuevoContacto.getTelefonoTrabajo();
			 * nuevoContacto.getNomCorreoElectronico();
			 */
		}
		return nuevoContacto;

	}

	/**
	 * Method for editing the information for the selected contact in the XML
	 * representation in memory.
	 * 
	 * @param index
	 *            Position of selected contact.
	 * @throws IOException
	 */
	public void editContact(Contactos nuevoContacto, int index) {
		if (dataroot != null && dataroot.getContactos() != null
				&& dataroot.getContactos().size() >= index && index > 0) {

			Contactos contacto = dataroot.getContactos().get(index - 1);

			/*
			 * InputStreamReader isr = new InputStreamReader(System.in);
			 * BufferedReader br = new BufferedReader(isr);
			 * System.out.print("Introduzca Nombre (o pulse 'Enter' para mantener '"
			 * +oldName+"'): "); String name = br.readLine(); if
			 * (name.isEmpty()) { name = oldName; } System.out.print(
			 * "Introduzca Apellidos (pulse 'Enter' para mantener '"
			 * +oldSurnames+"'): "); String surnames = br.readLine(); if
			 * (surnames.isEmpty()) { surnames = oldSurnames; }
			 * System.out.print(
			 * "Introduzca Telefono Contacto (pulse 'Enter' para mantener '"
			 * +oldPhone+"'): "); String phone = br.readLine(); if
			 * (phone.isEmpty()) { phone = oldPhone; } System.out.print(
			 * "Introduzca eMail Contacto (pulse 'Enter' para mantener '"
			 * +oldMail+"'): "); String mail = br.readLine(); if
			 * (mail.isEmpty()) { mail = oldMail; }
			 */

			contacto.setNombre(nuevoContacto.getNombre());
			contacto.setApellidos(nuevoContacto.getApellidos());
			contacto.setTelefonoTrabajo(nuevoContacto.getTelefonoTrabajo());
			contacto.setNomCorreoElectronico(nuevoContacto
					.getNomCorreoElectronico());
		}

		/*
		 * System.out.println("Se ha editado correctamente el contacto"); } else
		 * { System.out.println("No existe en la lista de contactos."); }
		 */
	}

	/**
	 * Removes the selected contact from the XML representation in memory.
	 * 
	 * @param index
	 *            Position of selected contact.
	 */
	public void deleteContact(int index) {
		if (dataroot != null && dataroot.getContactos() != null
				&& dataroot.getContactos().size() >= index) {
			dataroot.getContactos().remove(index - 1);
			// System.out.println("Contacto borrado.");
		} else {
			// System.out.println("No existe en la lista de contactos.");
		}
	}

	/**
	 * Writes the current XML in a file.
	 */
	public void saveXML() {
		if (dataroot != null) {
			try {
				JAXBContext jc = JAXBContext.newInstance(JAXB_PACKAGE);
				Marshaller marshaller = jc.createMarshaller();
				marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
				marshaller.marshal(dataroot, new File(XML_OUTPUT_PATH));
				// System.out.println("Se ha guardado correctamente el fichero "
				// + XML_OUTPUT_PATH);
			} catch (JAXBException ex) {
				System.err.println("Error al guardar los contactos del XML: "
						+ ex);
			}
		} /*
		 * else { System.out.println("Aun no existe ningun contacto"); }
		 */
	}

	/**
	 * Reads the input XML file.
	 */
	public void loadXML() {
		try {
			JAXBContext jc = JAXBContext.newInstance(JAXB_PACKAGE);
			Unmarshaller unmarshaller = jc.createUnmarshaller();
			dataroot = (Dataroot) unmarshaller.unmarshal(new File(
					XML_INPUT_PATH));
			// System.out.println("Se ha leido el fichero " + XML_INPUT_PATH);
		} catch (JAXBException ex) {
			System.err.println("Error al obtener los contactos del XML: " + ex);
		}
	}

	public List<String> searchByName(String name) {
		int resultados = 0;
		List<String> results = new ArrayList<String>();
		for (Contactos contact : dataroot.getContactos()) {
			if (contact.getNombre() != null
					&& contact.getNombre().equalsIgnoreCase(name)) {
				resultados++;
				results.add(contact.getNombre() + " " + contact.getApellidos());
			}
		}
		return results;
		/*
		 * if (resultados > 0) { System.out.println("Encontrados " + resultados
		 * + " resultados: "); for (int i = 0; i < results.size(); i++) {
		 * System.out.println(" Resultado " + (i + 1) + ": " + results.get(i));
		 * } } else { System.out.println("No se han encontrado resultados."); }
		 */
	}

	public List<String> searchByJob(String job) {
		int resultados = 0;
		List<String> results = new ArrayList<String>();
		for (Contactos contact : dataroot.getContactos()) {
			if (contact.getCargo() != null
					&& contact.getCargo().equalsIgnoreCase(job)) {
				resultados++;
				results.add(contact.getNombre() + " " + contact.getApellidos());
			}
		}
		return results;
		/*
		 * if (resultados > 0) { System.out.println("Encontrados " + resultados
		 * + " resultados: "); for (int i = 0; i < results.size(); i++) {
		 * System.out.println(" Resultado " + (i + 1) + ": " + results.get(i));
		 * } } else { System.out.println("No se han encontrado resultados."); }
		 */
	}

	public List<String> searchByPostalCode(String postalCode) {
		int resultados = 0;
		List<String> results = new ArrayList<String>();
		for (Contactos contact : dataroot.getContactos()) {
			if (contact.getCodPostal() != null
					&& contact.getCodPostal().equalsIgnoreCase(postalCode)) {
				resultados++;
				results.add(contact.getNombre() + " " + contact.getApellidos());
			}
		}
		return results;
		/*
		 * if (resultados > 0) { System.out.println("Encontrados " + resultados
		 * + " resultados: "); for (int i = 0; i < results.size(); i++) {
		 * System.out.println(" Resultado " + (i + 1) + ": " + results.get(i));
		 * } } else { System.out.println("No se han encontrado resultados."); }
		 */
	}

}